// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package config_dao

import (
	"fmt"

	"gitcode.com/opendragonfly/df_proto_gen_go.git/config_api"
	"github.com/dgraph-io/badger/v4"
	"google.golang.org/protobuf/proto"
)

const (
	_SECRET_NAME_SPACE = "secret"
)

type _SecretDao struct {
	dbh *badger.DB
}

func (db *_SecretDao) genKey(username string) string {
	return fmt.Sprintf("%s:%s", _SECRET_NAME_SPACE, username)
}

func (db *_SecretDao) List() ([]*config_api.AuthSecretInfo, error) {
	txn := db.dbh.NewTransaction(false)
	defer txn.Discard()

	keyPrefix := _SECRET_NAME_SPACE

	options := badger.IteratorOptions{
		PrefetchValues: true,
		PrefetchSize:   100,
		Reverse:        false,
		AllVersions:    false,
		Prefix:         []byte(keyPrefix),
	}
	iter := txn.NewIterator(options)
	defer iter.Close()

	retList := []*config_api.AuthSecretInfo{}

	for iter.Rewind(); iter.Valid(); iter.Next() {
		item := iter.Item()
		if item.IsDeletedOrExpired() {
			continue
		}
		value, err := item.ValueCopy(nil)
		if err != nil {
			return nil, err
		}
		info := &config_api.AuthSecretInfo{}
		err = proto.Unmarshal(value, info)
		if err != nil {
			return nil, err
		}
		retList = append(retList, info)
	}

	return retList, nil
}

func (db *_SecretDao) Set(secret *config_api.AuthSecretInfo) error {
	txn := db.dbh.NewTransaction(true)
	defer txn.Discard()

	key := db.genKey(secret.Username)
	value, err := proto.Marshal(secret)
	if err != nil {
		return err
	}
	err = txn.Set([]byte(key), value)
	if err != nil {
		return err
	}
	return txn.Commit()
}

func (db *_SecretDao) Get(username string) (*config_api.AuthSecretInfo, error) {
	txn := db.dbh.NewTransaction(false)
	defer txn.Discard()

	key := db.genKey(username)

	item, err := txn.Get([]byte(key))
	if err != nil {
		return nil, err
	}
	if item.IsDeletedOrExpired() {
		return nil, badger.ErrKeyNotFound
	}
	value, err := item.ValueCopy(nil)
	if err != nil {
		return nil, err
	}
	info := &config_api.AuthSecretInfo{}
	err = proto.Unmarshal(value, info)
	if err != nil {
		return nil, err
	}
	return info, nil
}

func (db *_SecretDao) Remove(username string) error {
	txn := db.dbh.NewTransaction(true)
	defer txn.Discard()

	key := db.genKey(username)
	err := txn.Delete([]byte(key))
	if err != nil {
		return err
	}
	return txn.Commit()
}
